package com.jse.ioc;

import java.util.List;

import com.jse.lang.born.Borning;

/**
     * 默认的对象编织过程
     * 
     * @author zozoh(zozohtnt@gmail.com)
     * @author wendal(wendal1985@gmail.com)
     */
public class ObjectWeaver {

        /**
         * 对象创建时的触发器
         */
        private IocEventTrigger<Object> create;

        /**
         * 对象构造方法
         */
        private Borning<?> borning;

        /**
         * 对象构造方法参数
         */
        private ValueProxy[] args;

        /**
         * 字段注入器列表
         */
        private FieldInjector[] fields;
        
        protected List<IocEventListener> listeners;
        
        protected String beanName;

        public void setCreate(IocEventTrigger<Object> create) {
            this.create = create;
        }

        public void setBorning(Borning<?> borning) {
            this.borning = borning;
        }

        public void setArgs(ValueProxy[] args) {
            this.args = args;
        }

        public void setFields(FieldInjector[] fields) {
            this.fields = fields;
        }
        
        public void setListeners(List<IocEventListener> listeners) {
            this.listeners = listeners;
        }

        /**
         * 根据容器构造时，为一个对象填充字段
         * 
         * @param ing
         *            容器构造时
         * @param obj
         *            对象，要被填充字段
         * 
         * @return 被填充后的字段
         */
        public <T> T fill(IocMaking ing, T obj) {
            // 设置字段的值
            for (FieldInjector fi : fields)
                fi.inject(ing, obj);
            return obj;
        }

        /**
         * 根据自身内容创建一个对象，并触发创建事件
         * 
         * @param ing
         *            容器构造时
         */
        public Object born(IocMaking ing) {
            // 准备构造函数参数
            Object[] args = new Object[this.args.length];
            for (int i = 0; i < args.length; i++)
                args[i] = this.args[i].get(ing);

            // 创建实例
            Object obj = borning.born(args);
            if (shallTrigger(obj)) {
                for (IocEventListener listener : listeners) {
                    obj = listener.afterBorn(obj, beanName);
                }
            }
            return obj;
        }

        /**
         * 为对象触发 CREATE 事件
         * 
         * @param obj
         *            对象
         */
        public Object onCreate(Object obj) {
            if (null != create && null != obj)
                create.trigger(obj);
            if (shallTrigger(obj)) {
                for (IocEventListener listener : listeners) {
                    obj = listener.afterCreate(obj, beanName);
                }
            }
            return obj;
        }
        
        protected boolean shallTrigger(Object obj) {
            return obj != null && listeners != null && !(obj instanceof IocEventListener) && listeners.size() > 0;
        }
        
        public void setBeanName(String beanName) {
            this.beanName = beanName;
        }

}
